import {
  NavigationGuardNext,
  RouteLocationNormalized,
  RouteRecordRaw,
} from "vue-router";

import NProgress from "@/utils/nprogress";
import { TOKEN_KEY } from "@/enums/CacheEnum";
import router from "@/router";
import { usePermissionStore, useUserStore, useSettingsStore } from "@/store";
import setPageTitle from "./setPageTitle";
import { LayoutEnum } from "@/enums/LayoutEnum";

export function setupPermission() {
  // 白名单路由
  const whiteList = ["/login"];

  router.beforeEach(async (to, from, next) => {
    NProgress.start();
    const hasToken = localStorage.getItem(TOKEN_KEY);
    const userStore = useUserStore();
    const settingsStore = useSettingsStore();
    const permissionStore = usePermissionStore();

    if (to.path === "/login" && hasToken) {
      next("/"); // 已登陆，但是访问了login页面
    } else if (whiteList.indexOf(to.path) !== -1) {
      next(); //白名单
    } else if (hasToken) {
      if (permissionStore.routes.length > 0) {
        if (to.matched.length === 0) {
          next("/404");
        } else {
          // 如果路由参数中有 title，覆盖路由元信息中的 title
          const title = to.params.title || to.query.title || to.meta.title;
          setPageTitle((title as string) || "未知错误");
          next();
        }
      } else {
        try {
          const user = await userStore.getUserInfo();
          const dynamicRoutes = await permissionStore.generateRoutes();
          dynamicRoutes.forEach((route: RouteRecordRaw) =>
            router.addRoute(route)
          );
          settingsStore.layout =
            user.isAdmin == 2 ? LayoutEnum.TOP : LayoutEnum.LEFT;
          next({ ...to, replace: true });
        } catch {
          await userStore.resetToken();
          redirectToLogin(to, next);
          NProgress.done();
        }
      }
    } else {
      next(`/login?redirect=${to.path}`);
    }
  });

  router.afterEach(() => {
    NProgress.done();
  });
}

/** 重定向到登录页 */
function redirectToLogin(
  to: RouteLocationNormalized,
  next: NavigationGuardNext
) {
  const params = new URLSearchParams(to.query as Record<string, string>);
  const queryString = params.toString();
  const redirect = queryString ? `${to.path}?${queryString}` : to.path;
  next(`/login?redirect=${encodeURIComponent(redirect)}`);
}
